<script lang="ts">
/**
 * 使用一个元素控制移动和缩放
 * 使用父级元素控制旋转和上下翻转
 * 父元素一定要和子元素大小一致，这样才不会有问题
 */

import {defineComponent} from 'vue'
import clickCountInTimeDecorator from "@/decorator/clickCountInTimeDecorator";
import CacheImg from "@/components/CacheImg/index.vue";
import DomMoveScale from "@/components/DomMoveScale/DomMoveScale.vue";
import typeOfUtils from "@/utils/type-of-utils.ts";
import {deepClone} from "@/utils";

const common = {
  rotate: 0,
  rotateY: false,
  rotateX: false,
  transform: {
    translateX: 0,
    translateY: 0,
    scale: 1,
  },
}

// @ts-ignore
export default defineComponent({
  name: "ImgDragWithResize",
  components: {DomMoveScale, CacheImg},
  props: {
    imageUrl: {
      type: String,
      required: true
    }
  },
  watch: {
    imageUrl() {
      this.init()
    }
  },
  data() {
    return {
      scaleRange: { max: 100, min: 0.1 },
      ...common,
      // 记录原始尺寸
      imgSize: {
        width: 0,
        height: 0
      },
      imgDisplayWidth: 0,    // 新增：图片显示宽度
      imgDisplayHeight: 0    // 新增：图片显示高度
    };
  },
  computed: {
    imgCenter() {
      return {
        x: this.transform.translateX + this.imgDisplayWidth * this.transform.scale / 2,
        y: this.transform.translateY + this.imgDisplayHeight * this.transform.scale / 2
      }
    },
    domMoveScaleStyle() {
      return {
        transform: `
        rotateZ(${this.rotate}deg)
        rotateY(${this.rotateY ? 180 : 0}deg)
        rotateX(${this.rotateX ? 180 : 0}deg)
        `,
        'transform-origin': `${this.imgCenter.x}px ${this.imgCenter.y}px`
      }
    },
    imageStyle() {
      return {
        transform: `translate3d(${this.transform.translateX}px, ${this.transform.translateY}px,0)
        scale3d(${this.transform.scale},${this.transform.scale},1)
        `,
      };
    }
  },
  methods: {
    init() {
      // 重新初始化数据
      Object.keys(common).forEach(key => {
        let value = common[key]
        if (typeOfUtils.isObject(value)) {
          this[key] = deepClone(value)
        } else {
          this[key] = value
        }
      })
    },
    @clickCountInTimeDecorator()
    dbClickInit() {
      this.init()
    },
    rotateFun(add: number) {
      this.rotate += add
    },
    // 缩放功能（保持中心）
    updateScale(diffScale: number) {
      const newScale = this.transform.scale + diffScale
      if (newScale < this.scaleRange.min || newScale > this.scaleRange.max) return
      this.transform.translateX = this.imgCenter.x - (this.imgDisplayWidth * newScale) / 2
      this.transform.translateY = this.imgCenter.y - (this.imgDisplayHeight * newScale) / 2
      // 应用新缩放值
      this.transform.scale = newScale
    },
    updateRotateY() {
      this.rotateY = !this.rotateY
    },
    updateRotateX() {
      this.rotateX = !this.rotateX
    },
    onResize({height, width}) {
      this.imgDisplayWidth = width
      this.imgDisplayHeight = height
    }
  }
})
</script>

<template>
  <el-auto-resizer :onResize="onResize">
    <template #default="{ height, width }">
      <DomMoveScale ref="DomMoveScaleRef"
                    @click="dbClickInit"
                    :style="domMoveScaleStyle"
                    v-model:transform="transform"
                    :max-scale="scaleRange.max"
                    :min-scale="scaleRange.min"
                    v-if="height && width">
        <CacheImg
          :src="imageUrl"
          :style="imageStyle"
          :zip-and-cache="false"
          ref="image"
        />
      </DomMoveScale>
    </template>
  </el-auto-resizer>
</template>

<style scoped lang="scss">
.el-auto-resizer{
  display: flex;
  align-items: center;
  justify-content: center;
  .DomMoveScale{
    height: 100%;
    width: 100%;
    transition: transform 0.2s;
    img{
      height: 100%;
      width: 100%;
      object-fit: scale-down;
    }
  }
}
</style>
